package com.zsd.android.opengldemo.shape;

import android.opengl.GLES20;
import android.opengl.Matrix;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

public class Triangle {

    static float triangleCoords[] = {
            0.5f, 0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f
    };
    private FloatBuffer vertexBuffer;
    //顶点着色器，是一门语言，GPU中执行的语言
    private String vertexShaderCode = "attribute vec4 vPosition;\n" +
            "uniform mat4 vMatrix;\n" +
            "void main(){\n" +
            "\tgl_Position = vMatrix * vPosition;\n" +
            "}";
    //片元着色器，是一门语言，GPU中执行的语言
    private String fragmentShaderCode = "precision mediump float;" +
            "uniform vec4 vColor;" +
            "void main() {" +
            "gl_FragColor = vColor;" +
            "}";
    float color[] = {1.0f, 1.0f, 1.0f, 1.0f};
    private int mProgram;
    private float[] mViewMatrix = new float[16];
    private float[] mProjectMatrix = new float[16];
    private float[] mMVPMatrix = new float[16];

    public Triangle() {
        //固定写法
        ByteBuffer bb = ByteBuffer.allocateDirect(triangleCoords.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        //把这门语法推送给GPU
        vertexBuffer.put(triangleCoords);
        vertexBuffer.position(0);

        //创建顶点着色器
        int shader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
        GLES20.glShaderSource(shader, vertexShaderCode);
        GLES20.glCompileShader(shader);

        //创建片元着色器
        int fragmentShader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
        GLES20.glShaderSource(fragmentShader, fragmentShaderCode);
        GLES20.glCompileShader(fragmentShader);

        //将顶点着色器和片元着色器放到统一程序中管理
        mProgram = GLES20.glCreateProgram();
        GLES20.glAttachShader(mProgram, shader);
        GLES20.glAttachShader(mProgram, fragmentShader);

        //连接到着色器程序
        GLES20.glLinkProgram(mProgram);

        //获取连接转态，如果连接失败就删除这个程序
        int[] linkStatus = new int[1];
        GLES20.glGetProgramiv(mProgram, GLES20.GL_LINK_STATUS, linkStatus, 0);
        if (linkStatus[0] == 0) {
            GLES20.glDeleteProgram(mProgram);
        }
    }

    public void onDrawFrame(GL10 gl) {
        // 渲染
        GLES20.glUseProgram(mProgram);

        //获取顶点着色器中的变量
        int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

        //打开（允许）对变量读写
        GLES20.glEnableVertexAttribArray(mPositionHandle);
        GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, vertexBuffer);

        //获取片元着色器中的变量
        int colorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
        GLES20.glUniform4fv(colorHandle, 1, color, 0);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

        //添加矩阵，用于适配，（OpenGL的坐标系和手机的坐标系不同）
        int mMatrixHandle = GLES20.glGetUniformLocation(mProgram, "vMatrix");
        GLES20.glUniformMatrix4fv(mMatrixHandle, 1, false, mMVPMatrix, 0);

        //关闭对变量的读写
        GLES20.glDisableVertexAttribArray(mPositionHandle);
    }

    /**
     * 固定写法
     * @param gl
     * @param width
     * @param height
     */
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        float ratio = width * 1.0f / height;
        //投影矩阵
        Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1, 1, 3, 120);

        Matrix.setLookAtM(mViewMatrix, 0,
                0, 0, 7,//摄像机坐标
                0f, 0f, 0f,//目标物的坐标
                0f, 1.0f, 0f//相机方向
        );
        //计算变换矩阵
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectMatrix, 0, mViewMatrix, 0);
    }
}
